package com.zjl.tools.util;

import java.io.*;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class FileUtil {

    public static void unzip(String zipFilePath, String destDirectory) {
        File destDir = new File(destDirectory);
        if (!destDir.exists()) {
            destDir.mkdir();
        }
        try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath))) {
            ZipEntry entry = zipIn.getNextEntry();
            // 读取zip文件中的每个条目（文件或文件夹）
            while (entry != null) {
                String filePath = destDirectory + File.separator + entry.getName();
                if (!entry.isDirectory()) {
                    // 如果是文件，则解压到目标目录
                    extractFile(zipIn, filePath);
                } else {
                    // 如果是目录，则创建目录结构
                    File dir = new File(filePath);
                    dir.mkdir();
                }
                zipIn.closeEntry();
                entry = zipIn.getNextEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath))) {
            byte[] bytesIn = new byte[4096];
            int read = 0;
            while ((read = zipIn.read(bytesIn)) != -1) {
                bos.write(bytesIn, 0, read);
            }
        }
    }

    //解压
    public static void decompression(String zipFilePath, String pathOut) {
        try (ZipInputStream zipInputStream =
                     new ZipInputStream(new FileInputStream(zipFilePath), Charset.forName("GBK"))) {
            byte[] buffer = new byte[40960];
            ZipEntry zipEntry;
            File newFile = new File(pathOut);
            newFile.mkdirs();
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                String fileName = zipEntry.getName();
                newFile = new File(pathOut + "/" + fileName);
                if (zipEntry.isDirectory()) {
                    newFile.mkdirs();
                } else {
                    try (FileOutputStream fileOutputStream = new FileOutputStream(newFile)) {
                        int len;
                        while ((len = zipInputStream.read(buffer)) > 0) {
                            fileOutputStream.write(buffer, 0, len);
                        }
                    }
                }
                zipInputStream.closeEntry();

            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //压缩文件
    public static void generateFile(String path) {

        generateFile(path, "zip");

    }

    public static void generateFile(String path, String format) {
        File file = new File(path);
        path = file.getAbsolutePath();
        if (!file.exists()) {
            return;
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(path + "." + format);
             ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream));
        ) {

            System.out.println(file.getName());
//            zipFile(zipOutputStream, file, file.getName());// 压缩
            zipFile(zipOutputStream, file, "");//
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void zipFile(ZipOutputStream out, File file, String dir) throws IOException {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            dir = dir.length() == 0 ? "" : dir + File.separator;
            for (File f : files) {
                zipFile(out, f, dir + f.getName());
            }
        } else {
            try (FileInputStream fileInputStream = new FileInputStream(file);) {

                out.putNextEntry(new ZipEntry(dir));
                int len;
                byte[] bytes = new byte[102400];
                while ((len = fileInputStream.read(bytes)) > 0) {
                    out.write(bytes, 0, len);
                }
            }

        }
    }

    //删除文件
    public static boolean deleteFile(String path) {
        File file = new File(path);
        if (file.exists()) {
            if (file.isFile()) {
                file.delete();
            } else {
                File[] files = file.listFiles();
                for (File f : files) {
                    deleteFile(f.getAbsolutePath());
                }
                file.delete();
            }
        } else {
            return false;
        }
        return true;
    }

    //获取本机IP
    public static String getLocalHost() {
        InetAddress localHost = null;
        try {
            localHost = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            return "UnknownHostException/127.0.0.1";
        }
        return localHost.toString();
    }

    //读文件内容
    public static String fileRead(String fileName) {
        fileName = fileName.trim();
        return fileRead(new File(fileName));
    }

    public static String fileRead(File file) {
        String reString = "{}";
        if (file.isFile()) {
            try (FileInputStream io = new FileInputStream(file);
                 ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                byte[] buf = new byte[102400];
                int len;
                while ((len = io.read(buf)) > 0) {
                    os.write(buf, 0, len);
                }
                return os.toString();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            throw new RuntimeException("只能读取文件");
        }
        return reString;
    }

    public static void fileWriter(String data, String filePathName) {
        fileWriter(data, filePathName, false);
    }

    public static void fileWriter(String data, String filePathName, boolean append) {
        fileWriter(data.getBytes(StandardCharsets.UTF_8), filePathName, append);
    }

    //写文件
    public static void fileWriter(InputStream bis, String filePathName, boolean append) {
        filePathName = filePathName.trim();
        File file = new File(filePathName);
        if (file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try (
                FileOutputStream fos = new FileOutputStream(filePathName, append);
        ) {
            byte[] buf = new byte[102400];
            int len;
            while ((len = bis.read(buf)) > 0) {
                fos.write(buf, 0, len);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public static void fileWriter(byte[] data, String filePathName, boolean append) {

        try (
                ByteArrayInputStream bis = new ByteArrayInputStream(data)
        ) {
            fileWriter(bis, filePathName, append);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void copyFile(File from, String to) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(102400);
        copyFile(from, new File(to), byteBuffer);
    }

    public static void copyFile(File from, File to, ByteBuffer byteBuffer) {
        FileInputStream fis = null;//创建一个输入流   内置有通道
        FileOutputStream fos = null;//创建一个输出流   内置有通道
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            fis = new FileInputStream(from);
            fos = new FileOutputStream(to);
            inputChannel = fis.getChannel();//获取对应的FileChannel
            outputChannel = fos.getChannel();//获取对应的FileChannel
            bufferCopyFile(byteBuffer, inputChannel, outputChannel);
            /**
             * //在linux下一个transferTo方法就可以完成传输
             * //在windows下- 次调用transferTo只能发送8M，就需要分段传输文件，而且要主要传输时的位置  现在好像没了
             * //transferTo底层使用到零拷贝
             */
//            inputChannel.transferTo(inputChannel.size(),0,outputChannel);///使用零拷贝   使用的是本机内存  谨慎使用
            long k = 0;
//            System.out.println(inputChannel.size());
//            while (k+8<<20<inputChannel.size()){
//                outputChannel.transferFrom(inputChannel,k,k+(8<<20));
//                k+=8<<20;
//            }
            outputChannel.transferFrom(inputChannel, k, inputChannel.size());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputChannel.close();
                outputChannel.close();
                fis.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //文件复制
    public static void copy(String from, String to) {
        copy(new File(from), to);
    }

    public static void copy(File from, String to) {
        if (from.getParentFile().exists()) {
            from.getParentFile().mkdirs();
        }
        try (FileInputStream fis = new FileInputStream(from);
             FileOutputStream fos = new FileOutputStream(to);
             BufferedOutputStream bos = new BufferedOutputStream(fos);
             BufferedInputStream bis = new BufferedInputStream(fis);
        ) {
            byte[] buf = new byte[20480];
            int len;
            while ((len = bis.read(buf)) > 0) {
                bos.write(buf, 0, len);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void bufferCopyFile(ByteBuffer byteBuffer, FileChannel inputChannel, FileChannel outputChannel) throws IOException {
        while (inputChannel.read(byteBuffer) > 0) {//将通道的信息读入到  Buffer
            byteBuffer.flip();
            //写入到FileChannel 通道
            outputChannel.write(byteBuffer);
            byteBuffer.clear();
        }
    }


    public static void main(String[] args) {
        String path = "D:\\Win10Driver\\OneDrive\\桌面\\xx\\新建文本文档.txt";
        String path2 = "D:\\Win10Driver\\OneDrive\\桌面\\xx\\新建文本文档2.txt";
//        generateFile("D:\\Win10Driver\\OneDrive\\桌面\\xx");

        decompression("D:\\Win10Driver\\OneDrive\\桌面\\xx.zip",
                "D:\\Win10Driver\\OneDrive\\桌面\\xxx\\a");
//        unzip("D:\\Win10Driver\\OneDrive\\桌面\\xxx\\xx.zip","D:\\Win10Driver\\OneDrive\\桌面\\xxx\\a");
//        deleteFile("D:\\Win10Driver\\OneDrive\\桌面\\xx\\新建文本文档.txt.zip");

//        System.out.println(getLocalHost());
//        String s = fileRead(path);
//        System.out.println(s);
//        fileWriter("xxx", path);
//        copy(path, path2);
    }

}
